home *** CD-ROM | disk | FTP | other *** search
/ CICA 1995 September (Japanese) / CICA Shareware for Windows CD-ROM (Walnut Creek) (September 1995) (Japanese) (Disc 2).iso / disc2 / nt / ntperf.exe / PERFTOOLS / SRC / PERFMON / PLAYBACK.C_ / PLAYBACK.C
Encoding:
C/C++ Source or Header  |  1993-05-15  |  22.0 KB  |  772 lines

  1. //==========================================================================//
  2. //                                  Includes                                //
  3. //==========================================================================//
  4.  
  5.  
  6. #include "perfmon.h"
  7. #include "playback.h"   // external declarations for this module
  8.  
  9. #include "bookmark.h"   // for BookmarkAppend
  10. #include "grafdata.h"   // for ResetGraph
  11. #include "perfdata.h"   // for UpdateLinesForSystem
  12. #include "perfmops.h"   // for SystemTimeDateString
  13. #include "log.h"
  14. #include "pmemory.h"    // for MemoryAllocate
  15. #include "fileutil.h"
  16. #include "utils.h"
  17. #include "alert.h"      // for ResetAlert
  18. #include "report.h"     // for ResetReport
  19.  
  20. NTSTATUS  AddNamesToArray (LPTSTR pNames,
  21.    DWORD    dwLastID,
  22.    LPWSTR   *lpCounterId) ;
  23.  
  24.  
  25. void  PlaybackAddCounterName (PLOGINDEX pIndex) ;
  26.  
  27. //==========================================================================//
  28. //                                   Macros                                 //
  29. //==========================================================================//
  30.  
  31.  
  32.  
  33. #define PointerSeek(pBase, lFileOffset)         \
  34.    ((PVOID) ((PBYTE) pBase + lFileOffset))
  35.  
  36.  
  37. //==========================================================================//
  38. //                              Local Functions                             //
  39. //==========================================================================//
  40.  
  41.  
  42. PVOID PlaybackSeek (long lFileOffset)
  43.    {  // PlaybackSeek
  44.    return (PointerSeek (PlaybackLog.pHeader, lFileOffset)) ;
  45.    }  // PlaybackSeek
  46.  
  47.  
  48. PLOGINDEXBLOCK FirstIndexBlock (PLOGHEADER pLogHeader)
  49.    {
  50.    return ((PLOGINDEXBLOCK) PointerSeek (pLogHeader, pLogHeader->iLength)) ;
  51.    }
  52.  
  53.  
  54. PLOGINDEX IndexFromPosition (PLOGPOSITION pLogPosition)
  55.    {
  56.    return (&pLogPosition->pIndexBlock->aIndexes [pLogPosition->iIndex]) ;
  57.    }
  58.  
  59.  
  60. PPERFDATA DataFromIndex (PLOGINDEX pLogIndex,
  61.                          LPTSTR lpszSystemName)
  62.    {
  63.    PPERFDATA pPerfData;
  64.    TCHAR     szLoggedComputerName[MAX_COMPUTERNAME_LENGTH + 3] ;
  65.    int       iNumSystem ;
  66.  
  67.    // Note: NULL lpszSystemName means return first logged system name
  68.    //       at the specified index.
  69.  
  70.    pPerfData = PlaybackSeek (pLogIndex->lDataOffset) ;
  71.  
  72.    for (iNumSystem = 0;
  73.         iNumSystem < pLogIndex->iSystemsLogged;
  74.         iNumSystem++)
  75.       {
  76.       if ( pPerfData &&
  77.            pPerfData->Signature[0] == (WCHAR)'P' &&
  78.            pPerfData->Signature[1] == (WCHAR)'E' &&
  79.            pPerfData->Signature[2] == (WCHAR)'R' &&
  80.            pPerfData->Signature[3] == (WCHAR)'F' )
  81.           {
  82.           GetPerfComputerName(pPerfData, szLoggedComputerName) ;
  83.           if (!lpszSystemName || strsamei(lpszSystemName, szLoggedComputerName))
  84.               {
  85.               return pPerfData ;
  86.               }
  87.           }
  88.        pPerfData = (PPERFDATA)((PBYTE) pPerfData +
  89.                                pPerfData->TotalByteLength) ;
  90.        }
  91.    return NULL ;
  92.    }
  93.  
  94.  
  95. PPERFDATA DataFromIndexPosition (PLOGPOSITION pLogPosition,
  96.                                  LPTSTR lpszSystemName)
  97.    {
  98.    PLOGINDEX      pLogIndex ;
  99. //   long           lDataFileOffset ;
  100.  
  101.    pLogIndex = IndexFromPosition (pLogPosition) ;
  102.    return (DataFromIndex (pLogIndex, lpszSystemName)) ;
  103.    }
  104.  
  105.  
  106. BOOL NextLogPosition (IN OUT PLOGPOSITION pLogPosition)
  107.    {
  108.    PLOGINDEXBLOCK pIndexBlock ;
  109.  
  110.    if (pLogPosition->pIndexBlock->iNumIndexes == 0)
  111.       {
  112.       // no data in this index block.  This is most likely
  113.       // a corrupted log file caused by system failure...
  114.       return (FALSE) ;
  115.       }
  116.  
  117.    if (pLogPosition->iIndex == pLogPosition->pIndexBlock->iNumIndexes - 1)
  118.       {
  119.       if (pLogPosition->pIndexBlock->lNextBlockOffset)
  120.          {
  121.          pIndexBlock = 
  122.             PlaybackSeek (pLogPosition->pIndexBlock->lNextBlockOffset) ;
  123.  
  124.          if (pIndexBlock->iNumIndexes == 0)
  125.             {
  126.             // no data in the next index block.  This is most likely
  127.             // a corrupted log file caused by system failure...
  128.             return (FALSE) ;
  129.             }
  130.          else
  131.             {
  132.             pLogPosition->pIndexBlock = pIndexBlock ;
  133.             pLogPosition->iIndex = 0 ;
  134.             return (TRUE) ;
  135.             }
  136.          }
  137.       else
  138.          return (FALSE) ;   
  139.       }
  140.    else
  141.       {
  142.       pLogPosition->iIndex++ ;
  143.       return (TRUE) ;
  144.       } 
  145.    }
  146.  
  147.  
  148. BOOL NextIndexPosition (IN OUT PLOGPOSITION pLogPosition,
  149.                         BOOL bCheckForNonDataIndexes)
  150. /*
  151.    Effect:        Set pLogPosition to the next log position from 
  152.                   the current position of pLogPosition if there is one.
  153.  
  154.    Returns:       Whether there was a next log position.
  155. */
  156.    {  // NextIndexPosition
  157.    LOGPOSITION    LP ;
  158.    PLOGINDEX      pIndex ;
  159.    PBOOKMARK      pBookmarkDisk, pBookmark ;
  160. //   LONG           lFilePosition ;
  161.  
  162.    pIndex = IndexFromPosition (pLogPosition) ;
  163.    
  164.    LP = *pLogPosition ;
  165.    pBookmark = NULL ;
  166.  
  167.    while (TRUE)
  168.       {  // while
  169.       if (!NextLogPosition (&LP))
  170.          return (FALSE) ;
  171.       pIndex = IndexFromPosition (&LP) ;
  172.  
  173.       if (pIndex && bCheckForNonDataIndexes && IsCounterNameIndex (pIndex))
  174.          {
  175.          PlaybackAddCounterName (pIndex) ;
  176.          }
  177.  
  178.       if (pIndex && bCheckForNonDataIndexes && IsBookmarkIndex (pIndex))
  179.          {
  180.          if (pBookmark)
  181.             {
  182.             // this is the case when several bookmarks are
  183.             // found before any data index...
  184.             pBookmark->iTic = PlaybackLog.iTotalTics ;
  185.             BookmarkAppend (&PlaybackLog.pBookmarkFirst, pBookmark) ;
  186.             }
  187.  
  188.          pBookmarkDisk = PlaybackSeek (pIndex->lDataOffset) ;
  189.          pBookmark = MemoryAllocate (sizeof (BOOKMARK)) ;
  190.          *pBookmark = *pBookmarkDisk;
  191.          pBookmark->pBookmarkNext = NULL ;
  192.          }
  193.  
  194.       if (pIndex && IsDataIndex (pIndex))
  195.          {
  196.          LP.iPosition++ ;
  197.          *pLogPosition = LP ;
  198.          if (pBookmark)
  199.             {
  200.             pBookmark->iTic = PlaybackLog.iTotalTics ;
  201.             BookmarkAppend (&PlaybackLog.pBookmarkFirst, pBookmark) ;
  202.             }
  203.          return (TRUE) ;
  204.          }
  205.       }  // while
  206.    }  // NextIndexPosition
  207.  
  208.  
  209. BOOL NextReLogIndexPosition (IN OUT PLOGPOSITION pLogPosition)
  210. /*
  211.    Effect:        Set pLogPosition to the next log position from 
  212.                   the current position of pLogPosition if there is one.
  213.                   Will return bookmarks, counternames, or data.
  214.  
  215.    Returns:       Whether there was a next relog position.
  216. */
  217.    {  // NextReLogIndexPosition
  218.    LOGPOSITION    LP ;
  219.    PLOGINDEX      pIndex ;
  220. //   LONG           lFilePosition ;
  221.  
  222.    pIndex = IndexFromPosition (pLogPosition) ;
  223.    
  224.    LP = *pLogPosition ;
  225.  
  226.    if (!NextLogPosition (&LP))
  227.       return (FALSE) ;
  228.    pIndex = IndexFromPosition (&LP) ;
  229.  
  230.    if (pIndex && IsDataIndex (pIndex))
  231.       {
  232.       LP.iPosition++ ;
  233.       }
  234.    *pLogPosition = LP ;
  235.    return (TRUE) ;
  236.    }  // NextReLogIndexPosition
  237.  
  238.  
  239.  
  240.  
  241.    
  242. //==========================================================================//
  243. //                             Exported Functions                           //
  244. //==========================================================================//
  245.  
  246.  
  247. void PlaybackInitializeInstance (void)
  248.    {  // PlaybackInitializeInstance
  249.    PlaybackLog.iStatus = iPMStatusClosed ;
  250.    PlaybackLog.hFile = NULL ;
  251.  
  252.    PlaybackLog.szFilePath  = MemoryAllocate (FilePathLen * sizeof (TCHAR)) ;
  253.    PlaybackLog.szFileTitle = MemoryAllocate (FilePathLen * sizeof (TCHAR)) ;
  254.    lstrcpy (PlaybackLog.szFilePath,  szDefaultLogFileName) ;
  255.    lstrcpy (PlaybackLog.szFileTitle, szDefaultLogFileName) ;
  256.    }  // PlaybackInitializeInstance
  257.  
  258.  
  259. INT OpenPlayback (LPTSTR lpszFilePath, LPTSTR lpszFileTitle)
  260.    {  // OpenPlayback
  261.    BOOL     bFirstTime = TRUE ;
  262.  
  263.    lstrcpy  (PlaybackLog.szFilePath, lpszFilePath) ;
  264.    lstrcpy  (PlaybackLog.szFileTitle, lpszFileTitle) ;
  265.    PlaybackLog.hFile = FileHandleOpen (lpszFilePath) ;
  266.    if (!PlaybackLog.hFile || PlaybackLog.hFile == INVALID_HANDLE_VALUE)
  267.       {
  268.       return (ERR_CANT_OPEN) ;
  269.       }
  270.  
  271.    PlaybackLog.pHeader = (PLOGHEADER) FileMap (PlaybackLog.hFile,
  272.       &PlaybackLog.hMapHandle) ;
  273.    
  274.    if (!PlaybackLog.pHeader)
  275.       {
  276.       if (PlaybackLog.hMapHandle)
  277.          {
  278.          CloseHandle (PlaybackLog.hMapHandle) ;
  279.          }
  280.  
  281.       CloseHandle (PlaybackLog.hFile) ;
  282.       return (ERR_CANT_OPEN) ;
  283.       }
  284.  
  285.    if (!strsame (PlaybackLog.pHeader->szSignature, LogFileSignature))
  286.       {
  287.       FileUnMap((LPVOID)PlaybackLog.pHeader, PlaybackLog.hMapHandle) ;
  288.       CloseHandle (PlaybackLog.hFile) ;
  289.       return (ERR_BAD_LOG_FILE) ;
  290.       }
  291.  
  292.    PlaybackLog.BeginIndexPos.pIndexBlock = FirstIndexBlock (PlaybackLog.pHeader) ;
  293.    PlaybackLog.BeginIndexPos.iIndex = 0 ;
  294.    PlaybackLog.BeginIndexPos.iPosition = 0 ;
  295.    PlaybackLog.pBookmarkFirst = NULL ;
  296.  
  297.    PlaybackLog.iTotalTics = 1 ;
  298.    PlaybackLog.EndIndexPos = PlaybackLog.BeginIndexPos ;
  299.    while (NextIndexPosition (&PlaybackLog.EndIndexPos, TRUE))
  300.       {
  301.       if (bFirstTime)
  302.          {
  303.          // set the begin index to the first data index
  304.          bFirstTime = FALSE ;
  305.          PlaybackLog.BeginIndexPos.iIndex =
  306.             PlaybackLog.EndIndexPos.iIndex ;
  307.          }
  308.       else
  309.          {
  310.          PlaybackLog.iTotalTics++ ;
  311.          }
  312.       }
  313.  
  314.    if (PlaybackLog.iTotalTics == 1 )
  315.       {
  316.       // no data inside the log file.  It must be a corrupted
  317.       // log file
  318.       FileUnMap((LPVOID)PlaybackLog.pHeader, PlaybackLog.hMapHandle) ;
  319.       CloseHandle (PlaybackLog.hFile) ;
  320.       return (ERR_CORRUPT_LOG) ;
  321.       }
  322.  
  323. //   PlaybackLog.StartIndexPos = PlaybackLog.BeginIndexPos ;
  324.  
  325.    // getthe first data index
  326.    if (!LogPositionN (1, &(PlaybackLog.StartIndexPos)))
  327.       {
  328.       PlaybackLog.StartIndexPos = PlaybackLog.BeginIndexPos ;
  329.       }
  330.  
  331.    PlaybackLog.StopIndexPos = PlaybackLog.EndIndexPos ;
  332.    PlaybackLog.StopIndexPos.iPosition =
  333.       min (PlaybackLog.StopIndexPos.iPosition,
  334.            PlaybackLog.iTotalTics - 1 ) ;
  335.  
  336.  
  337.    PlaybackLog.iSelectedTics = PlaybackLog.iTotalTics ;
  338.  
  339.    PlaybackLog.iStatus = iPMStatusPlaying ;
  340.    return (0) ;   
  341.    }  // OpenPlayback
  342.  
  343.  
  344. void CloseInputLog (HWND hWndParent)
  345.    {  // CloseInputLog
  346.    PBOOKMARK      pBookmark, pNextBookmark ;
  347.    BOOL           retCode, retCode1 ;
  348.    PLOGCOUNTERNAME pLogCounterName, pNextCounterName ;
  349.  
  350.    UNREFERENCED_PARAMETER (hWndParent) ;
  351.  
  352.    // free the bookmark list
  353.    for (pBookmark = PlaybackLog.pBookmarkFirst ;
  354.       pBookmark ;
  355.       pBookmark = pNextBookmark )
  356.       {
  357.       // save next bookmark and free current bookmark
  358.       pNextBookmark = pBookmark->pBookmarkNext ;
  359.       MemoryFree (pBookmark) ;
  360.       }
  361.    PlaybackLog.pBookmarkFirst = NULL ;
  362.  
  363.    // free all counter names stuff
  364.    if (PlaybackLog.pBaseCounterNames)
  365.       {
  366.       MemoryFree (PlaybackLog.pBaseCounterNames) ;
  367.       }
  368.    PlaybackLog.pBaseCounterNames = NULL ;
  369.    PlaybackLog.lBaseCounterNameSize = 0 ;
  370.    PlaybackLog.lBaseCounterNameOffset = 0 ;
  371.  
  372.    for (pLogCounterName = PlaybackLog.pLogCounterNameFirst ;
  373.       pLogCounterName ;
  374.       pLogCounterName = pNextCounterName)
  375.       {
  376.       pNextCounterName = pLogCounterName->pCounterNameNext ;
  377.       MemoryFree (pLogCounterName->pRemainNames) ;
  378.       MemoryFree (pLogCounterName) ;
  379.       }
  380.  
  381.    PlaybackLog.pLogCounterNameFirst = NULL ;
  382.  
  383.    retCode1 = FileUnMap((LPVOID)PlaybackLog.pHeader, PlaybackLog.hMapHandle) ;
  384.    retCode = CloseHandle (PlaybackLog.hFile) ;
  385.    PlaybackLog.iStatus = iPMStatusClosed ;
  386.  
  387.    ResetGraphView (hWndGraph) ;
  388.    ResetAlertView (hWndAlert) ;
  389.    ResetLogView (hWndLog) ;
  390.    ResetReportView (hWndReport) ;
  391.    }
  392.  
  393.  
  394.  
  395. BOOL LogPositionN (int iIndex, PLOGPOSITION pLP)
  396.    {  // LogPositionN
  397.    LOGPOSITION    LP ;
  398.    int            i ;
  399.  
  400.    LP = PlaybackLog.BeginIndexPos ;
  401.    for (i = 0 ;
  402.         i < iIndex ;
  403.         i++)
  404.       {
  405.       if (!NextIndexPosition (&LP, FALSE))
  406.          return (FALSE) ;
  407.       }
  408.  
  409.    *pLP = LP ;
  410.    return (TRUE) ;
  411.    }  // LogPositionN
  412.  
  413.  
  414. PLOGINDEX PlaybackIndexN (int iIndex)
  415.    {
  416.    LOGPOSITION    LP ;
  417.    int            i ;
  418.  
  419.    LP = PlaybackLog.BeginIndexPos ;
  420.    for (i = 0 ;
  421.         i < iIndex ;
  422.         i++)
  423.       {
  424.       if (!NextIndexPosition (&LP, FALSE))
  425.          return (NULL) ;
  426.       }
  427.  
  428.    return (IndexFromPosition (&LP)) ;
  429.    }
  430.  
  431.  
  432. BOOL PlaybackLines (PPERFSYSTEM pSystemFirst,
  433.                     PLINE pLineFirst,
  434.                     int iLogTic)
  435.    {  // PlaybackLines
  436.  
  437.    PLOGINDEX      pLogIndex ;
  438.    PPERFDATA      pPerfData ;
  439.    PPERFSYSTEM       pSystem ;
  440.    BOOL           bAnyFound ;
  441.  
  442.    pLogIndex = PlaybackIndexN (iLogTic) ;
  443.    if (!pLogIndex)
  444.       return (FALSE) ;
  445.  
  446.    bAnyFound = FALSE ;
  447.    for (pSystem = pSystemFirst ;
  448.         pSystem ;
  449.         pSystem = pSystem->pSystemNext)
  450.       {  // for
  451.       pPerfData = DataFromIndex (pLogIndex, pSystem->sysName) ;
  452.       if (pPerfData)
  453.          {
  454.          UpdateLinesForSystem (pSystem->sysName,
  455.                                pPerfData,
  456.                                pLineFirst) ;
  457.          bAnyFound = TRUE ;
  458.          }
  459.       else
  460.          {
  461.          FailedLinesForSystem (pSystem->sysName,
  462.                                pPerfData,
  463.                                pLineFirst) ;
  464.          }
  465.       }
  466.    return (bAnyFound) ;
  467.    }  // PlaybackLines
  468.  
  469.  
  470.  
  471.  
  472. PPERFDATA LogDataFromPosition (PPERFSYSTEM pSystem, 
  473.                                PLOGPOSITION pLogPosition)
  474.    {  // LogDataFromPosition
  475.    PLOGINDEX      pLogIndex ;
  476.    
  477.  
  478.    if (!pLogPosition)
  479.       return (NULL) ;
  480.  
  481.    pLogIndex = IndexFromPosition (pLogPosition) ;
  482.    if (!pLogIndex)
  483.       return (NULL) ;
  484.    
  485.    return (DataFromIndex (pLogIndex, pSystem->sysName)) ;
  486.    }  // LogDataFromPosition
  487.  
  488.  
  489.  
  490. BOOL LogPositionSystemTime (PLOGPOSITION pLP, SYSTEMTIME *pSystemTime)
  491. /*
  492.    Effect:        Given a logposition, get the index entry for that position
  493.                   and return the system time stored therein.
  494. */
  495.    {  // LogPositionSystemTime
  496.    PLOGINDEX      pLogIndex ;
  497.  
  498.    pLogIndex = IndexFromPosition (pLP) ;
  499.    if (!pLogIndex)
  500.       return (FALSE) ;
  501.  
  502.    *pSystemTime = pLogIndex->SystemTime ;
  503.    }  // LogPositionSystemTime
  504.  
  505.  
  506. int LogPositionIntervalSeconds (PLOGPOSITION pLPStart, 
  507.                                 PLOGPOSITION pLPStop)
  508. /*
  509.    Effect:        Return the time difference (in seconds) between the
  510.                   system times of the two specified log positions.
  511. */
  512.    {  // LogPositionIntervalSeconds
  513.    SYSTEMTIME     SystemTimeStart ;
  514.    SYSTEMTIME     SystemTimeStop ;
  515.  
  516.  
  517.    if (LogPositionSystemTime (pLPStart, &SystemTimeStart) &&
  518.        LogPositionSystemTime (pLPStop, &SystemTimeStop))
  519.       return (SystemTimeDifference (&SystemTimeStart, &SystemTimeStop)) ;
  520.    else
  521.       return (0) ;
  522.    }  // LogPositionIntervalSeconds
  523.  
  524.  
  525.  
  526. int PlaybackSelectedSeconds (void)
  527.    {  // PlaybackSelectedSeconds
  528.    return (LogPositionIntervalSeconds (&PlaybackLog.StartIndexPos, 
  529.                                        &PlaybackLog.StopIndexPos)) ;
  530.    }  // PlaybackSelectedSeconds
  531.  
  532. void BuildLogComputerList (HWND hDlg, int DlgID)
  533.    {
  534.    PPERFDATA pPerfData;
  535.    int       iNumSystem ;
  536.    HWND      hListBox = GetDlgItem (hDlg, DlgID) ;
  537.    PLOGINDEX pLogIndex ;
  538.    TCHAR     szLoggedComputerName[MAX_COMPUTERNAME_LENGTH + 3] ;
  539.  
  540.    pLogIndex = IndexFromPosition (&(PlaybackLog.StartIndexPos)) ;
  541.    pPerfData = PlaybackSeek (pLogIndex->lDataOffset) ;
  542.  
  543.    for (iNumSystem = 0;
  544.         iNumSystem < pLogIndex->iSystemsLogged;
  545.         iNumSystem++)
  546.       {
  547.       if ( pPerfData &&
  548.            pPerfData->Signature[0] == (WCHAR)'P' &&
  549.            pPerfData->Signature[1] == (WCHAR)'E' &&
  550.            pPerfData->Signature[2] == (WCHAR)'R' &&
  551.            pPerfData->Signature[3] == (WCHAR)'F' )
  552.           {
  553.           GetPerfComputerName(pPerfData, szLoggedComputerName) ;
  554.           LBAdd (hListBox, szLoggedComputerName) ;
  555.           }
  556.        pPerfData = (PPERFDATA)((PBYTE) pPerfData +
  557.                                pPerfData->TotalByteLength) ;
  558.        }
  559.    }  // BuildLogComputerList
  560.  
  561. void  PlaybackAddCounterName (PLOGINDEX pIndex)
  562. {
  563.    PLOGCOUNTERNAME      pLogCounterName, pListCounterName ;
  564.    PLOGFILECOUNTERNAME  pDiskCounterName ;
  565.    PVOID                pCounterData ;
  566.    BOOL                 bExist = FALSE ;
  567.  
  568.    pDiskCounterName = PlaybackSeek (pIndex->lDataOffset) ;
  569.  
  570.    // check we have a record for this system
  571.    for (pListCounterName = PlaybackLog.pLogCounterNameFirst ;
  572.         pListCounterName ;
  573.         pListCounterName = pListCounterName->pCounterNameNext)
  574.       {
  575.       if (strsamei(pDiskCounterName->szComputer,
  576.          pListCounterName->CounterName.szComputer))
  577.          {
  578.          // found!
  579.          pLogCounterName = pListCounterName ;
  580.          bExist = TRUE ;
  581.          break ;
  582.          }
  583.       }
  584.  
  585.    if (!bExist)
  586.       {
  587.       // new counter name record
  588.       if (!(pLogCounterName = MemoryAllocate (sizeof(LOGCOUNTERNAME))))
  589.          {
  590.          return ;
  591.          }
  592.       }
  593.    else
  594.       {
  595.       // free old memory in previous counter name record.
  596.       if (pLogCounterName->pRemainNames)
  597.          {
  598.          MemoryFree (pLogCounterName->pRemainNames) ;
  599.          }
  600.       pLogCounterName->pRemainNames = NULL ;
  601.       }
  602.  
  603.    pLogCounterName->CounterName = *pDiskCounterName ;
  604.  
  605.    if (pDiskCounterName->lBaseCounterNameOffset == 0)
  606.       {
  607.       // this is the base counter names, 
  608.       // get the master copy of the counter names
  609.  
  610.       if (!(pCounterData =
  611.             MemoryAllocate (pDiskCounterName->lUnmatchCounterNames)))
  612.          {
  613.          MemoryFree (pLogCounterName) ;
  614.          return ;
  615.          }
  616.  
  617.       // free the old one if it exists.
  618.       if (PlaybackLog.pBaseCounterNames)
  619.          {
  620.          MemoryFree (PlaybackLog.pBaseCounterNames) ;
  621.          }
  622.    
  623.       PlaybackLog.pBaseCounterNames = pCounterData ;
  624.  
  625.       pCounterData =
  626.          PlaybackSeek (pDiskCounterName->lCurrentCounterNameOffset) ;
  627.  
  628.       memcpy (PlaybackLog.pBaseCounterNames,
  629.          pCounterData,
  630.          pDiskCounterName->lUnmatchCounterNames) ;
  631.  
  632.       PlaybackLog.lBaseCounterNameSize =
  633.          pDiskCounterName->lUnmatchCounterNames ;
  634.  
  635.       PlaybackLog.lBaseCounterNameOffset =
  636.          pDiskCounterName->lBaseCounterNameOffset ;
  637.       }
  638.    else if (pDiskCounterName->lUnmatchCounterNames)
  639.       {
  640.       // this is not a based system and it has extra counter names
  641.       // allocate a buffer to hold them
  642.       pLogCounterName->pRemainNames =
  643.          MemoryAllocate (pDiskCounterName->lUnmatchCounterNames) ;
  644.  
  645.       if (pLogCounterName->pRemainNames)
  646.          {
  647.          pCounterData =
  648.             PlaybackSeek (pDiskCounterName->lCurrentCounterNameOffset) ;
  649.  
  650.          memcpy(pLogCounterName->pRemainNames,
  651.             pCounterData,
  652.             pDiskCounterName->lUnmatchCounterNames) ;
  653.          }
  654.       }
  655.  
  656.    if (!bExist)
  657.       {
  658.       // now add the new counter name record to the linked list
  659.       if (!PlaybackLog.pLogCounterNameFirst)
  660.          {
  661.          PlaybackLog.pLogCounterNameFirst = pLogCounterName ;
  662.          }
  663.       else
  664.          {
  665.          for (pListCounterName = PlaybackLog.pLogCounterNameFirst ;
  666.             pListCounterName->pCounterNameNext ;
  667.             pListCounterName = pListCounterName->pCounterNameNext)
  668.             {
  669.             // do nothing until we get to the end of the list
  670.             ;
  671.             }
  672.          pListCounterName->pCounterNameNext = pLogCounterName ;
  673.          }
  674.       }
  675.  
  676. }  // PlaybackAddCounterName
  677.  
  678.  
  679. LPWSTR *LogBuildNameTable (PPERFSYSTEM pSysInfo)
  680. {
  681.  
  682.    DWORD             dwArraySize ;
  683.    PLOGCOUNTERNAME   pCounterName ;
  684.    LPWSTR            *lpCounterId = NULL ;
  685.    LPWSTR            lpCounterNames ;
  686.    NTSTATUS          Status ;
  687.  
  688.    for (pCounterName = PlaybackLog.pLogCounterNameFirst ;
  689.         pCounterName ;
  690.         pCounterName = pCounterName->pCounterNameNext)
  691.       {
  692.       if (strsamei (pSysInfo->sysName, pCounterName->CounterName.szComputer))
  693.          {
  694.          // found the right system
  695.          break ;
  696.          }
  697.       }
  698.    if (!pCounterName)
  699.       {
  700.       goto ERROR_EXIT ;
  701.       }
  702.  
  703.    dwArraySize = (pCounterName->CounterName.dwLastCounterId + 1)
  704.       * sizeof (LPWSTR) ;
  705.  
  706.    lpCounterId = MemoryAllocate (dwArraySize +
  707.       pCounterName->CounterName.lMatchLength +
  708.       pCounterName->CounterName.lUnmatchCounterNames ) ;
  709.  
  710.    if (!lpCounterId)
  711.       {
  712.       goto ERROR_EXIT ;
  713.       }
  714.  
  715.    // initialize pointers into buffer
  716.  
  717.    lpCounterNames = (LPWSTR)((LPBYTE)lpCounterId + dwArraySize);
  718.    if (pCounterName->CounterName.lBaseCounterNameOffset == 0)
  719.       {
  720.       // this is the base system
  721.       memcpy(lpCounterNames,
  722.          PlaybackLog.pBaseCounterNames,
  723.          PlaybackLog.lBaseCounterNameSize) ;
  724.       }
  725.    else
  726.       {
  727.       // copy the matched portion from the base system
  728.       memcpy(lpCounterNames,
  729.          PlaybackLog.pBaseCounterNames,
  730.          pCounterName->CounterName.lMatchLength) ;
  731.  
  732.       // copy the unmatched portion
  733.       if (pCounterName->CounterName.lUnmatchCounterNames)
  734.          {
  735.          memcpy(((PBYTE)lpCounterNames +
  736.             pCounterName->CounterName.lMatchLength),
  737.             pCounterName->pRemainNames,
  738.             pCounterName->CounterName.lUnmatchCounterNames) ;
  739.          }
  740.       }
  741.  
  742.    Status = AddNamesToArray (lpCounterNames,
  743.       pCounterName->CounterName.dwLastCounterId,
  744.       lpCounterId) ;
  745.  
  746.    if (Status != ERROR_SUCCESS)
  747.       {
  748.       goto ERROR_EXIT ;
  749.       }
  750.  
  751.    pSysInfo->CounterInfo.dwLastId =
  752.       pCounterName->CounterName.dwLastCounterId ;
  753.    pSysInfo->CounterInfo.dwLangId =
  754.       pCounterName->CounterName.dwLangId ;
  755.    pSysInfo->CounterInfo.dwHelpSize = 0 ;
  756.    pSysInfo->CounterInfo.dwCounterSize =
  757.       pCounterName->CounterName.lMatchLength +
  758.       pCounterName->CounterName.lUnmatchCounterNames ;
  759.    
  760.    return (lpCounterId) ;
  761.  
  762. ERROR_EXIT:
  763.    if (lpCounterId)
  764.       {
  765.       MemoryFree (lpCounterId) ;
  766.       }
  767.    return (NULL) ;
  768. } // LogBuildNameTable
  769.  
  770.     
  771. 
  772.